package templateExecel2.fram;

import com.google.common.base.Joiner;
import templateExecel2.utils.StringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class TemplateCellParser {

    private static Pattern ARRAY_PATTERN = Pattern.compile("(?<=[(,]|^) *([^\\[\\],()0-9_.][^\\[\\],().]*(\\[[a-z][a-z0-9]*])*(\\.[^\\[\\],()0-9_.][^\\[\\],().]*(\\[[a-z][a-z0-9]*])*)*) *(?=[,)]|$)");

    static class Result {

        private LinkedHashMap<String, LinkedHashSet<String>> checkJsMap;

        LinkedHashMap<String, LinkedHashSet<String>> getCheckJsMap() {
            return checkJsMap;
        }

        private String expression;

        String getExpression() {
            return expression;
        }

        private List<String> commands;

        public List<String> getCommands() {
            return commands;
        }
    }

    //表达式${xxx}
    private static Pattern EXPRESSION_PATTERN = Pattern.compile("\\$\\{([^{}]*)}");

    private static String handleExpression(String s) {

        Matcher matcher = EXPRESSION_PATTERN.matcher(s);

        int end = 0;

        List<String> all = new LinkedList<>();
        while (matcher.find()) {
            if (matcher.start() > end) {


                String st = "'" + s.substring(end, matcher.start()).replace("'", "\\\'") + "'";
                all.add(st);
            }
            String group = matcher.group(1);
            all.add(group);
            end = matcher.end();
        }

        if (all.size() > 0) {
            if (end < s.length() - 1) {
                all.add("'" + s.substring(end).replace("'", "\\\\'") + "'");
            }
            String join = Joiner.on(",").join(all);
            return "concat(" + join + ")";
        } else {
            return "'" + s + "'";
        }
    }

    private static Pattern command_patten = Pattern.compile("\\$[a-z]+\\([a-z0-9]*\\)");

    private static void handleCommand(String s, Result result) {
        Matcher matcher = command_patten.matcher(s);

        if (matcher.find()) {
            result.commands = new ArrayList<>();
            result.commands.add(matcher.group());
        }

        while (matcher.find()) {
            if (!result.commands.contains(matcher.group())) {
                result.commands.add(matcher.group());
            }
        }
    }


    /*
        变换数组
     */

    //提取数组引用
    static Result parse(String s) {//提取并变换数组表达式

        s = handleExpression(s);//对换行符进行一次转换

        //替换掉换行符
        s = s.replace("\n", "\\n");

        //对s中的换行符再进行一次转译

        Result result = new Result();

        //提取指令
        handleCommand(s, result);

        result.checkJsMap = new LinkedHashMap<>();

        //首先提取字符串
        StringUtils.StringRecover extract = StringUtils.extract(s);
        s = extract.getResult();

        //提取数组表达式
        Matcher matcher = ARRAY_PATTERN.matcher(s);

        int end = 0;

        StringBuilder builder = new StringBuilder();


        //从一个简单的操作
        while (matcher.find()) {

            builder.append(s, end, matcher.start());
            end = matcher.end();
            String group = matcher.group(1);

            String[] split = group.split(" *\\. *");
            //分析出变量
            A[] as = new A[split.length];
            for (int i = 0; i < split.length; i++) {
                as[i] = new A();
                String[] strings = split[i].split("[\\[\\]]+");

                //对索引添加索引标记
                as[i].name = strings[0];

                String[] indexs = new String[strings.length - 1];

                //TODO 替换变量索引??
                System.arraycopy(strings, 1, indexs, 0, strings.length - 1);

                as[i].indexs = indexs;
                as[i].getLengthCheckJs();

            }
            B b = new B();
            b.as = as;


            //放入
            b.fillCheckJs(result.checkJsMap);

            //TODO  变换数组声明??
            //  String name = b.toString();
            builder.append(group);

            //放入表达式映射
            //result.paramsMap.put(name, group);
        }




        builder.append(s.substring(end));
        s = builder.toString();

        //恢复字符串
        s = extract.recover(s);

        builder.delete(0, builder.length());

   /*     result.paramsMap.forEach((k, v) -> {
            builder.append("var ").append(k).append("=").append(v).append(";\n");
        });
*/
        result.expression = builder.append(s).toString();

        return result;

    }


    private static class B {//多维度控制
        private A[] as;

    /*    @Override
        public String toString() {
            return Joiner.on("").join(as);
        }
*/
        /*
            a[i].b[i][j]

            -->分解
            1. a[i].b[]
         */

        //获取检查js
        public void fillCheckJs(LinkedHashMap<String, LinkedHashSet<String>> map) {

            if (as == null) {
                return;
            }
            StringBuilder builder = new StringBuilder();
            for (A a : as) {
                C[] lengthCheckJs = a.getLengthCheckJs();

                if (lengthCheckJs != null) {
                    for (C c : lengthCheckJs) {

                        //分隔开
                        String checkJ = c.js;

                        //进行分隔处理
                        String[] split = checkJ.split("&&");

                        String[] sl = new String[split.length];

                        for (int i = 0; i < split.length; i++) {
                            sl[i] = builder + split[i];
                        }

                        LinkedHashSet<String> linkedHashSet = map.computeIfAbsent(c.index, f -> new LinkedHashSet<>());
                        linkedHashSet.add(Joiner.on("&&").join(sl));
                    }
                    builder.append(a.arrayString).append(".");
                }
            }
        }

    }


    /*

        a[i][j]

        -->分解
        1.  a[i]&&a[i].length>j?null:'j'
        2.  a&&a.length>i?null:'i'

     */
    private static class A {
        private String name;
        private String[] indexs;
        private String arrayString;

        //一个数组
        public C[] getLengthCheckJs() {

            if (indexs == null) {
                return null;
            }

            //每个维度一个
            C[] r = new C[indexs.length];

            StringBuilder h = new StringBuilder(name);

            for (int i = 0; i < indexs.length; i++) {

                //对于遍历的元素必须具备.length才有遍历的意义
                String js = h + "&&" + h + ".length" + "&&" + h + ".length>" + indexs[i] + "?false:true;";//返回是否已经超出预期值
                C c = new C();
                c.js = js;
                c.index = indexs[i];
                r[i] = c;

                h.append("[").append(indexs[i]).append("]");
            }

            arrayString = h.toString();

            return r;
        }

      /*  @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();

            //.append("__PARAM_")
            builder.append(name);

            if (indexs != null) {
                for (String index : indexs) {
                    builder.append("_").append(index);
                }
            }
            return builder.toString();
        }*/
    }

    private static class C {
        private String index;
        private String js;
    }


    public static void main(String[] args) {//对i的校验是无效的

        Pattern pattern = Pattern.compile("\\[[^\\[\\]]+]");

        String s = "${concat(fill(list[j])[i])}";

        Matcher matcher = pattern.matcher(s);

        while (matcher.find()) {

            //成对的反向括号
            StringUtils.SubStringResult reverse = StringUtils.pairingSubStringReverse(s, matcher.start(), ')', '(');
            StringUtils.SubStringResult subStringResult;

            String exp = "";

            //如果不存在
            if (reverse == null) {
                subStringResult = StringUtils.rejectCharSubStringReverse(s, matcher.start() - 1, ',', '(');
            } else {
                exp = reverse.getSubString();
                if (reverse.getEnd() == matcher.start()) {
                    subStringResult = StringUtils.rejectCharSubStringReverse(s, reverse.getStart() - 1, ',', '(');
                } else {
                    subStringResult = StringUtils.rejectCharSubStringReverse(s, matcher.start() - 1, ',', '(');
                }
            }

            if (subStringResult != null) {
                exp = subStringResult.getSubString() + exp;

                System.out.println(exp);

            } else {
                throw new RuntimeException("无效表达式:" + s.substring(0, matcher.end()));
            }

        }
    }

}
